package outils;

import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JOptionPane;
import modele.Plateau;
import modele.case_.Case;

/**
 *
 * @author gervaila
 */
public class Outils {

	/**
	 * une instance de Random
	 */
	public static Random rand = new Random();

	/**
	 *
	 * @param i
	 * @param borneInf
	 * @param borneSup
	 * @return vrai si l'entier i est compris entre borneInf et borneSup, faux
	 * sinon
	 */
	public static boolean estDansBorne(int i, int borneInf, int borneSup) {
		return i >= borneInf && i <= borneSup;
	}

	/**
	 *
	 * @param i
	 * @param borneInf
	 * @param borneSup
	 * @return vrai si l'entier i est compris entre borneInf+1 et borneSup-1,
	 * faux sinon
	 */
	public static boolean estDansBorneExcluses(int i, int borneInf, int borneSup) {
		return estDansBorne(i, borneInf + 1, borneSup - 1);
	}

	/**
	 *
	 * @param n
	 * @return le signe de n
	 */
	public static int signe(double n) {
		if (n > 0) {
			return 1;
		} else if (n < 0) {
			return -1;
		} else {
			return 0;
		}
	}

	/**
	 *
	 * @param cible centre du cercle
	 * @param plateau le plateau de jeu
	 * @param rayon le rayon du cercle
	 * @return les cases présentent dans le cercle défini par le rayon 'rayon'
	 * et le centre 'cible'
	 */
	public static ArrayList<Case> cercle(Case cible, Plateau plateau, double rayon) {
		ArrayList<Case> resultat = new ArrayList<Case>();

		for (int x = (int) Math.floor(cible.getX() - rayon); x <= Math.ceil(cible.getX() + rayon); x++) {
			for (int y = (int) Math.floor(cible.getY() - rayon); y <= Math.ceil(cible.getY() + rayon); y++) {
				if (plateau.getCase(x, y) != null) {
					if ((cible.getX() - x) * (cible.getX() - x) + (cible.getY() - y) * (cible.getY() - y) <= ((rayon - 0.9) * (rayon - 0.9))) {
						resultat.add(plateau.getCase(x, y));
					}
				}
			}
		}

		return resultat;
	}

	/**
	 *
	 * @param source la source de la demie droite
	 * @param destination la destination de la demie droite
	 * @param plateau le plateau de jeu
	 * @return les cases présentent sur la demie droite [source,destination)
	 */
	public static ArrayList<Case> demieDroite(Case source, Case destination, Plateau plateau) {
		ArrayList<Case> cases = new ArrayList<Case>();
		int dx1 = destination.getX() - source.getX();
		int dy1 = destination.getY() - source.getY();

		if (dx1 == 0 && dy1 == 0) {
			return cases;
		} else if (Math.abs(dx1) < Math.abs(dy1)) {
			int dy = signe(dy1);
			int maxY = dy < 0 ? -1 : plateau.getHauteur();
			for (int y = source.getY(); y != maxY; y += dy) {
				int x = Math.round((float) (y - source.getY()) / dy1 * dx1) + source.getX();
				Case c = plateau.getCase(x, y);
				if (c != null) {
					cases.add(c);
				}
			}
		} else {
			int dx = signe(dx1);
			int maxX = dx < 0 ? -1 : plateau.getLargeur();
			for (int x = source.getX(); x != maxX; x += dx) {
				int y = Math.round((float) (x - source.getX()) / dx1 * dy1) + source.getY();
				Case c = plateau.getCase(x, y);
				if (c != null) {
					cases.add(c);
				}
			}
		}
		cases.remove(0);
		return cases;
	}

	/**
	 * calcule la coordonnée polaire theta
	 *
	 * @param dx l'abscisse en coordonnées cartésiennes
	 * @param dy l'ordonnée en coordonnées cartésiennes
	 * @return l'angle theta
	 */
	public static Double theta(int dx, int dy) {
		Double angle;
		if (dx == 0 && dy == 0) {
			angle = null;
		} else if (dx == 0) {
			if (dy > 0) {
				angle = Math.PI / 2;
			} else {
				angle = -Math.PI / 2;
			}
		} else {
			angle = Math.atan((double) dy / dx);
			if (dx < 0) {
				angle += Math.PI;
			}
		}
		return angle;
	}

	/**
	 *
	 * @param a
	 * @param b
	 * @return l'angle theta entre deux points a et b par rapport a l'horizontal
	 */
	public static Double theta(Point a, Point b) {
		return theta(b.x - a.x, b.y - a.y);
	}

	/**
	 * Affiche un JOptionPane d'erreur contenant le message 'message'
	 *
	 * @param message le message d'erreur
	 * @see JOptionPane
	 */
	public static void erreur(String message) {
		JOptionPane.showMessageDialog(null, message);
	}
}
